#include "Camera.h"
#include "RayTracer.h"
#include "Scene.h"
#include "RayTracer.h"
#include "TaskBasedThread.h"
#include "Counter.h"
#include <cassert>

void TaskBasedThread::vProcess()
{
    while(m_tActive)
    {
        if(m_shouldWait)
        {
            ResetEvent(m_event);
            DWORD d = WaitForSingleObject(m_event, INFINITE);
            if(d == WAIT_FAILED)
            {
                assert(0);
            }
        }
        if(m_tActive && !m_shouldWait)
        {
            Counter c;
            Ray_Trace_Task t(0,0,0,0);
            m_numTasksCompleted = 0;
            Color cMask(1,1,1,1);
            while(m_scene->GetTask(t))
            {
                if(m_whichMask == 1)
                    cMask = m_personalMask;
                else if(m_whichMask == 2)
                    cMask.SetAll(t.colorMask[0],t.colorMask[1],t.colorMask[2]);
                m_numTasksCompleted++;
                Color finalColor;
                Ray ray;
                ray.m_origin = (m_cam->GetPos());

                for(int x = t.start[0]; x < t.finish[0]; ++x )
                    for(int y = t.start[1]; y < t.finish[1]; ++y)
                    {
                        m_cam->ComputeDirection(x,y, &ray.m_dir,m_scene);
                        ray.m_depth = -1.0f;
                        ray.m_hitObject = NULL;
                        //Trace it
                        finalColor = m_rt->TraceRay(ray);
                        finalColor *= cMask;
                        if(m_scene->TrySetDepth(x,y,ray.m_depth))
                        {
                            m_scene->SetPixelColor(x, y, finalColor);
                        }
                    }
            }
            if(m_numTasksCompleted > 0)
            {
                double average = c.GetCounter() / m_numTasksCompleted;
                m_numTasksCompleted = 0;
                m_scene->SetTimer(m_threadID, average);
            }
            else
                m_scene->SetTimer(m_threadID, 0);
        }        
        //if no more jobs left, notifty scene and then puase yourself
        m_scene->ThreadFinished();
        vPause();
    }    
    m_scene->ThreadEnded();
}